<?php
/**
 * @author spenceryg
 * @date 2022/12/8
 * @time 9:42 下午
 * @focus love & life
 */


namespace app\auto\lib;


use app\auto\business\TableBusiness;
use app\auto\model\App;
use app\auto\model\Controller;
use app\auto\model\Method;
use app\auto\model\MethodFiled;
use app\auto\model\Table;
use CodeSinging\ComponentBuilder\Builder;
use Laminas\Code\Generator\ValueGenerator;
use pQuery;
use think\facade\Db;
use think\helper\Str;

class ViewGenerator
{

    /**
     * getRealConfigData
     * @param $in
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getRealConfigData($in)
    {
        $res = [];
        $in_field = \app\auto\model\Field::find($in['field_id']);
        $in_table = \app\auto\model\Table::find($in_field['table_id']);
        $in['table_name'] = $in_table['name'];
        $in['field_name'] = $in_field['name'];
        $in['fields'] = \app\auto\model\Field::where('table_id', $in_table['id'])->select();
        $in['alias'] = str_replace(env('DATABASE.PREFIX'), '', $in_table['name']) . '__' . $in_field['name'];

        $res = $in['config'];
        $res['name'] = $in['alias'];
        $res['field_data'] = $in_field;
        return $res;

    }


    /**
     * sp_radio
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_radio($data, bool $is_update = false, bool $is_label = true): string
    {

        $content = '';
        $content .= "{foreach \${$data['name']}_options as \$option}";
        if ($is_update) {
            $content .= "<input name=\"{$data['name']}\" type=\"radio\" value=\"{\$option.id}\" title='{\$option.name}'  checked=\"{\$r.{$data['name']} == \$option.id ? 'checked': ''}\" />";
        } else {
            $content .= "<input name=\"{$data['name']}\" type=\"radio\" value=\"{\$option.id}\" title='{\$option.name}' />";
        }
        $content .= "{/foreach}";


        $dom = self::wrapper($data, $content);

        $label = $is_label ? self::label($data)->build() : '';
        $mid = $data['mid'] ? self::mid($data['mid']) : '';
        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * select
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_select($data, bool $is_update = false, bool $is_label = true): string
    {

        if ($data['field_data']['is_relation']) {
            $data['comment'] = str_replace('关联id', '', $data['comment']);

        }
        $attr = [
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'select2',
            'lay-ignore' => 'lay-ignore',
            'style' => 'width: 100%;'
        ];

        $content = '<option value="">请选择</option>';
        $content .= "{foreach \${$data['name']}_options as \$option}";
        if ($is_update) {
            $content .= "<option value=\"{\$option.id}\" checked=\"{\$r.{$data['name']} == \$option.id ? 'selected': ''}\">{\$option.name}</option>";
        } else {
            $content .= "<option value=\"{\$option.id}\">{\$option.name}</option>";
        }
        $content .= "{/foreach}";

        $dom = (new Builder('select', $content, $attr));
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data)->build() : '';
        $mid = $data['mid'] ? self::mid($data['mid']) : '';
        return $label . "" . $dom->build() . "" . $mid;


    }

    /**
     * input
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_input($data, bool $is_update = false, bool $is_label = true): string
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input',
            'placeholder' => '请输入' . $data['comment']
        ];
        if ($is_update) {
            $attr['value'] = "{\$r['" . $data['name'] . "']}";
        }
        $dom = new Builder('input', '', $attr, false);
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data)->build() : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sc_time_range
     * @param $data
     * @param bool $is_label
     */
    public static function sc_time_range($data, bool $is_label = true)
    {
        $map = [
            0 => ['yyyy-MM-dd HH:mm:ss', 'Y-m-d H:i:s', 'datetime'],
            1 => ['yyyy-MM-dd HH:mm', 'Y-m-d H:i', 'datetime'],
            2 => ['yyyy-MM-dd HH', 'Y-m-d H', 'datetime'],
            3 => ['MM-dd HH:mm:ss', 'm-d H:i:s', 'datetime'],
            4 => ['MM-dd HH:mm', 'm-d H:i', 'datetime'],
            5 => ['MM-dd HH', 'm-d H', 'datetime'],
            6 => ['HH:mm:ss', 'H:i:s', 'time'],
            7 => ['HH:mm', 'H:i', 'time'],
            8 => ['HH', 'H', 'time'],
        ];

        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input form-date',
            'readonly' => 'readonly',
            'placeholder' => '请选择' . $data['comment'],
            'data-type' => $map[$data['date']][2],
            'data-format' => $map[$data['date']][0]
        ];

        $attr_start = $attr;
        $attr_start['name'] .= '_start';
        $attr_start['id'] .= '_start';
        $attr_start['placeholder'] = str_replace('请选择', '开始', $attr_start['placeholder']);
        $attr_start['value'] = <<<EOF
{:input('{$attr_start['name']}')}
EOF;
        $attr_end = $attr;
        $attr_end['name'] .= '_end';
        $attr_end['id'] .= '_end';
        $attr_end['placeholder'] = str_replace('请选择', '结束', $attr_end['placeholder']);
        $attr_end['value'] = <<<EOF
{:input('{$attr_end['name']}')}
EOF;

        $dom_start = new Builder('input', '', $attr_start, false);
        $dom_end = new Builder('input', '', $attr_end, false);
        $data['is_inline'] = 1;
        $dom = (new Builder('div', $dom_start->build() . $dom_end->build(), [
            'style' => "display: flex;",
            'class' => "layui-input-inline"
        ]));
        $label = $is_label ? self::label($data)->build() : '';
        $html = $dom->build();

        return <<<EOF
<div class='layui-inline'>
$label
$html
</div>
EOF;

    }

    public static function sc_date_range($data, bool $is_label = true)
    {
        $map = [
            0 => ['yyyy-MM-dd', 'Y-m-d', 'date'],
            1 => ['yyyy-MM', 'Y-m', 'month'],
            2 => ['MM-dd', 'm-d', 'date'],
            3 => ['yyyy', 'Y', 'year']
        ];

        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input form-date',
            'readonly' => 'readonly',
            'placeholder' => '请选择' . $data['comment'],
            'data-type' => $map[$data['date']][2],
            'data-format' => $map[$data['date']][0]
        ];

        $attr_start = $attr;
        $attr_start['name'] .= '_start';
        $attr_start['id'] .= '_start';
        $attr_start['value'] = <<<EOF
{:input('{$attr_start['name']}')}
EOF;
        $attr_end = $attr;
        $attr_end['name'] .= '_end';
        $attr_end['id'] .= '_end';
        $attr_end['value'] = <<<EOF
{:input('{$attr_end['name']}')}
EOF;

        $dom_start = new Builder('input', '', $attr_start, false);
        $dom_end = new Builder('input', '', $attr_end, false);
        $data['is_inline'] = 1;
        $dom = (new Builder('div', $dom_start->build() . $dom_end->build(), [
            'style' => "display:flex;",
            'class' => "layui-input-inline"
        ]));
        $label = $is_label ? self::label($data)->build() : '';
        $html = $dom->build();

        return <<<EOF
<div class='layui-inline'>
$label
$html
</div>
EOF;


    }


    /**
     * sc_input
     * @param $data
     * @param bool $is_label
     * @return string
     */
    public static function sc_input($data, bool $is_label = true)
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input',
            'placeholder' => '请输入' . $data['comment'],
            'value' => "{:input('" . $data['name'] . "')}"

        ];
        $data['is_inline'] = 1;
        $dom = new Builder('input', '', $attr, false);
        $dom = self::wrapper($data, $dom);
        $label = $is_label ? self::label($data)->build() : '';
        $html = $dom->build();

        return <<<EOF
<div class='layui-inline'>
$label
$html
</div>
EOF;

    }

    public static function sc_relation_select($data, $is_label = true)
    {
        $data['comment'] = $data['field_data']->iTable->comment;

        $attr = [
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'select2',
            'lay-ignore' => 'lay-ignore',
            'style' => 'min-width: 100px;'
        ];

        $content = '<option value="">请选择</option>';
        $content .= "{foreach \${$data['name']}_options as \$option}";
        $content .= "<option value=\"{\$option.id}\" checked=\"{\$Request.param.{$data['name']} == \$option.id ? 'selected': ''}\">{\$option.name}</option>";

        $content .= "{/foreach}";

        $dom = (new Builder('select', $content, $attr));

        $data['is_inline'] = 1;
        $dom = self::wrapper($data, $dom);
        $label = $is_label ? self::label($data)->build() : '';
        $html = $dom->build();

        return <<<EOF
<div class='layui-inline'>
$label
$html
</div>
EOF;
    }


    public static function sc_select($data, bool $is_label = true)
    {

        $attr = [
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'select2',
            'lay-ignore' => 'lay-ignore',
            'style' => 'min-width: 100px;'
        ];

        $content = '<option value="">请选择</option>';
        $content .= "{foreach \${$data['name']}_options as \$option}";
        $content .= "<option value=\"{\$option.id}\" checked=\"{\$Request.param.{$data['name']} == \$option.id ? 'selected': ''}\">{\$option.name}</option>";

        $content .= "{/foreach}";

        $dom = (new Builder('select', $content, $attr));

        $data['is_inline'] = 1;
        $dom = self::wrapper($data, $dom);
        $label = $is_label ? self::label($data)->build() : '';
        $html = $dom->build();

        return <<<EOF
<div class='layui-inline'>
$label
$html
</div>
EOF;
    }


    /**
     * getDataSetOptions
     * @param $data
     * @param bool $is_map
     * @return array
     */
    public static function getDataSetOptions($data, bool $is_map = false): array
    {

        $option_arr = [];
        $data_set = trim($data['data_set']);
        if ($data['is_sql']) {
            $option_arr = Db::query($data_set);
        } else {
            $line_arr = explode("\r\n", $data_set);
            foreach ($line_arr as $line_str) {
                if ($line_str === '') {
                    continue;
                }
                if (strpos($line_str, '__') !== false) {
                    [$this_id, $this_name] = explode('__', $line_str, 2);
                    $option_arr[] = [
                        'name' => $this_name,
                        'id' => $this_id
                    ];
                } else {
                    $option_arr[] = [
                        'name' => $line_str,
                        'id' => $line_str
                    ];
                }
            }
        }
        if ($is_map) {
            $map = [];
            foreach ($option_arr as $item) {
                $map[$item['id']] = $item['name'];
            }
            return $map;
        }
        return $option_arr;
    }


    /**
     * image
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_image($data, bool $is_update = false, bool $is_label = true): string
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'readonly' => 'readonly',
            'class' => 'layui-input',
            'placeholder' => '请输入' . $data['comment'],
        ];
        if ($is_update) {
            $attr['value'] = "{\$r['" . $data['name'] . "']}";
        }
        $dom = (new Builder('input', '', $attr, false));
        $dom = self::wrapper($data, $dom);


        $label = $is_label ? self::label($data)->build() : '';

        $mid = <<<EOF
<div class="layui-btn-group" style="position: absolute;top:0;right: 0;padding-left: 5px;background-color: white">
    <button type="button" class="layui-btn " onclick="previewImg('{$data['name']}')"><i class="layui-icon">&#xe64a;</i>预览</button>
    <button type="button" class="layui-btn  fastupimg" data-input_id="{$data['name']}" data-listtype="img" id="{$data['name']}_Picker"><i class="layui-icon">&#xe608;</i>上传</button>
    <button type="button" class="layui-btn " onClick="selectfile('{$data['name']}','','img')"><i class="layui-icon">&#xe67c;</i>浏览</button>
</div>
EOF;

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sp_file
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_video($data, bool $is_update = false, bool $is_label = true): string
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'readonly' => 'readonly',
            'class' => 'layui-input',
            'placeholder' => '请输入' . $data['comment'],
        ];
        if ($is_update) {
            $attr['value'] = "{\$r['" . $data['name'] . "']}";
        }
        $dom = (new Builder('input', '', $attr, false));
        $dom = self::wrapper($data, $dom);


        $label = $is_label ? self::label($data)->build() : '';

        $mid = <<<EOF
<div class="layui-btn-group" style="position: absolute;top:0;right: 0;padding-left: 5px;background-color: white">
			<button type="button" class="layui-btn" onclick="playVideo('{$data['name']}')"><i class="layui-icon">&#xe6ed;</i>播放</button>
    <button type="button" class="layui-btn  fastupimg" data-input_id="{$data['name']}" data-listtype="video" id="{$data['name']}_Picker"><i class="layui-icon">&#xe608;</i>上传</button>
    <button type="button" class="layui-btn " onClick="selectfile('{$data['name']}','','video')"><i class="layui-icon">&#xe67c;</i>浏览</button>
</div>
EOF;

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sp_video
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_file($data, bool $is_update = false, bool $is_label = true): string
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'readonly' => 'readonly',
            'class' => 'layui-input',
            'placeholder' => '请输入' . $data['comment'],
        ];
        if ($is_update) {
            $attr['value'] = "{\$r['" . $data['name'] . "']}";
        }
        $dom = (new Builder('input', '', $attr, false));
        $dom = self::wrapper($data, $dom);


        $label = $is_label ? self::label($data)->build() : '';

        $mid = <<<EOF
<div class="layui-btn-group" style="position: absolute;top:0;right: 0;padding-left: 5px;background-color: white">
    <button type="button" class="layui-btn " onclick="downloadFile('{$data['name']}')"><i class="layui-icon">&#xe601;</i>下载</button>
    <button type="button" class="layui-btn  fastupimg" data-input_id="{$data['name']}" data-listtype="file" id="{$data['name']}_Picker"><i class="layui-icon">&#xe608;</i>上传</button>
    <button type="button" class="layui-btn " onClick="selectfile('{$data['name']}','','file')"><i class="layui-icon">&#xe67c;</i>浏览</button>
</div>
EOF;

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sp_date
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_date($data, bool $is_update = false, bool $is_label = true): string
    {
        $map = [
            0 => ['yyyy-MM-dd', 'Y-m-d', 'date'],
            1 => ['yyyy-MM', 'Y-m', 'month'],
            2 => ['MM-dd', 'm-d', 'date'],
            3 => ['yyyy', 'Y', 'year']
        ];

        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input form-date',
            'readonly' => 'readonly',
            'placeholder' => '请选择' . $data['comment'],
            'data-type' => $map[$data['date']][2],
            'data-format' => $map[$data['date']][0]
        ];
        if ($is_update) {
            $attr['value'] = <<<EOF
{\$r['{$data['name']}']?date('{$map[$data['date']][1]}',\$r['{$data['name']}']):''}
EOF;

        }
        $dom = new Builder('input', '', $attr, false);
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data)->build() : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sp_time
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_time($data, bool $is_update = false, bool $is_label = true): string
    {
        $map = [
            0 => ['yyyy-MM-dd HH:mm:ss', 'Y-m-d H:i:s', 'datetime'],
            1 => ['yyyy-MM-dd HH:mm', 'Y-m-d H:i', 'datetime'],
            2 => ['yyyy-MM-dd HH', 'Y-m-d H', 'datetime'],
            3 => ['MM-dd HH:mm:ss', 'm-d H:i:s', 'datetime'],
            4 => ['MM-dd HH:mm', 'm-d H:i', 'datetime'],
            5 => ['MM-dd HH', 'm-d H', 'datetime'],
            6 => ['HH:mm:ss', 'H:i:s', 'time'],
            7 => ['HH:mm', 'H:i', 'time'],
            8 => ['HH', 'H', 'time'],
        ];

        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-input form-date',
            'readonly' => 'readonly',
            'placeholder' => '请选择' . $data['comment'],
            'data-type' => $map[$data['date']][2],
            'data-format' => $map[$data['date']][0]
        ];
        if ($is_update) {
            $attr['value'] = <<<EOF
{\$r['{$data['name']}']?date('{$map[$data['date']][1]}',\$r['{$data['name']}']):''}
EOF;
        }
        $dom = new Builder('input', '', $attr, false);
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data)->build() : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';

        return $label . "" . $dom->build() . "" . $mid;
    }


    /**
     * sp_morepic
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_morepic($data, bool $is_update = false, bool $is_label = true)
    {
        $code = <<<EIF
	<label class="layui-form-label " id="info_{$data['name']}">{$data['comment']}</label>
    <div class="layui-input-block morepic">
        <div class="morepic_box">
            <div class="piclist" data-field="{$data['name']}">
                <ul id="{$data['name']}_piclist_ul">
                    <?php
                    if(\$r){
                        \$morepic = \$r['{$data['name']}'];
                       \$morepic_arr = explode("\\r\\n",\$morepic);
                        foreach(\$morepic_arr as \$v){
                            if(!\$v){break;};
                            \$vs=explode("||",\$v);
                    ?>

                    <li title="拖动我是可以排序的哦" draggable="false">
                        <a class="piclist_img {$data['name']}_fancybox" rel="{$data['name']}_rel" title="<?=\$vs[2]?>" href="<?=\$vs[1]?>">
                            <img src="<?=\$vs[0]?>" draggable="false">
                            <input type="hidden" name="{$data['name']}_smallimg[]" value="<?=\$vs[0]?>">
                            <input type="hidden" name="{$data['name']}_bigimg[]" value="<?=\$vs[1]?>">
                        </a>
                        <div class="piclist_title"><input type="text" name="{$data['name']}_imgname[]" value="<?=\$vs[2]?>"></div>
                        <div class="file-panel"><span class="cancel" onclick="delete_li(this)" title="删除图片">删除</span></div>
                    </li>
                    <?php
                        }                     
                    }
                    ?>
                    <li class="add_morepic" id="{$data['name']}_add_button" title="增加图片" onclick="selectfiles('{$data['name']}',moreimg,'img','{imgwidth}','{imgheight}')">
                        <div class="piclist_img">+</div>
                    </li>                                                
                    <div class="clear"></div>
                </ul>
            </div>                                        
        </div>
    </div>
    <div class="layui-form-mid layui-word-aux">{$data['mid']}</div>
EIF;
        return $code;

    }


    public static function sp_baidumap($data, bool $is_update = false, bool $is_label = true)
    {
        $attr = [
            'type' => "hidden",
            'name' => $data['name'],
            'id' => $data['name'] . '_map_point',
            'autocomplete' => 'false',
            'class' => 'map_point',
        ];
        if ($is_update) {
            $attr['value'] = "{\$r['" . $data['name'] . "']}";
        }
        $real_dom = (new Builder('input', '', $attr, false));
        $dom = (new Builder('div', '', ['class' => 'controls map_show', 'id' => $data['name'] . '_mapshow', 'style' => 'height:400px;']));
        $search_html = <<<EOF
	<input type="text" id="{$data['name']}_search_val" value="{\$r?explode('|',\$r['{$data['name']}'])[1]:''}" placeholder="请输入精确的地址，便于地图定位。" class="layui-input map_search_value"  style="width:60%" autocomplete="off">
        <input type="button" value="定位" id="{$data['name']}_search_button" class="layui-btn layui-btn-primary map_search_button">
EOF;

        $dom = self::wrapper($data, $dom);
        $dom->add($search_html)->add($real_dom);

        $label = $is_label ? self::label($data)->build() : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';

        $js = <<<EOF
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak={:config('app.baidu_map_key')}"></script>
EOF;

        return $label . "" . $dom->build() . "" . $mid . $js;
    }

    /**
     * sp_editor
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_editor($data, bool $is_update = false, bool $is_label = true)
    {
        $dom = <<<EOF
<div class="news_editor" editor_name="{$data['name']}" editor_width="100%" editor_height="800" imgwidth="" imgheight="">
<script id="{$data['name']}" name="{$data['name']}" type="text/plain">{\$r?htmlspecialchars_decode(\$r['{$data['name']}']):'{$data['field_data']['default']}'}</script>
</div>
        远程图片保存本地<input type="checkbox" name="{$data['name']}_saveFile" lay-ignore value="1" checked> &nbsp;&nbsp;
        提取第一张图做为缩略图（如果缩略图为空的情况下）<input type="checkbox" lay-ignore  name="{$data['name']}_getFirstImg" value="1">
EOF;
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data)->build() : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';

        return $label . "" . $dom->build() . "" . $mid;

    }


    /**
     * textarea
     * @param $data
     * @param bool $is_update
     * @param bool $is_label
     * @return string
     */
    public static function sp_textarea($data, bool $is_update = false, bool $is_label = true): string
    {
        $attr = [
            'type' => "text",
            'name' => $data['name'],
            'id' => 'form_' . $data['name'],
            'autocomplete' => 'false',
            'class' => 'layui-textarea',
            'placeholder' => '请输入' . $data['comment']
        ];

        $dom = (new Builder('textarea', '', $attr));
        if ($is_update) {
            $dom = (new Builder('textarea', '{$r[\'' . $data['name'] . '\']}', $attr));
        }
        $dom = self::wrapper($data, $dom);

        $label = $is_label ? self::label($data) : '';

        $mid = $data['mid'] ? self::mid($data['mid']) : '';
        $dom->add(self::mid($data['mid']));

        return $label . "" . $dom->build() . "" . $mid;
    }


    public static function mid($content): string
    {

        return $content ? '<div class="layui-form-mid layui-word-aux">' . $content . '</div>' : '';
    }


    /**
     * wrapper
     * @param $data
     * @param Builder|string $dom
     * @return Builder
     */
    public static function wrapper($data, $dom): Builder
    {
        if ($data['is_inline']) {
            $attr = [
                'class' => 'layui-input-inline'
            ];
        } else {
            $attr = [
                'class' => 'layui-input-block'
            ];
        }
        if ($data['type'] == 'baidumap') {
            $attr['class'] .= ' baidu_map_field';
        }
        return (new Builder('div', $dom, $attr));
    }

    /**
     * label
     * @param $data
     * @return Builder
     */
    public static function label($data): Builder
    {
        $attr = [
            'class' => 'layui-form-label'
        ];
        return (new Builder('label', $data['comment'], $attr));

    }


    /**
     * generate
     * @param $method
     * @throws \Gajus\Dindent\Exception\RuntimeException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function generate($method)
    {
        $type = $method['type'];
        $request = $method['request'];
        $code = '';
        if ($method['is_user_view']) {
            $code = $method['view_code'];
        } else {
            if ($request == 'get_view' && $type == 'list') {
                $code = self::methodListViewCode($method);
            }
            if ($request == 'post_view' && $type == 'add') {
                $code = self::methodAddViewCode($method);
            }
            if ($request == 'post_view' && $type == 'update') {
                $code = self::methodUpdateViewCode($method);
            }

        }

        if ($code) {
            $code = self::purifier($code);
            $code = preg_replace('/checked="([\w\W]+?)"/', '\1', $code);

            $file_path = self::getViewPath($method);
            file_put_contents($file_path, $code);
            Method::update([
                'id' => $method['id'],
                'view_code' => $code
            ]);

        }

    }


    /**
     * add模版代码
     * getAddViewCode
     * @param $method
     * @return string
     * @throws \Gajus\Dindent\Exception\RuntimeException
     */
    public static function methodAddViewCode($method): string
    {
        $html = file_get_contents('../app/auto/template/add.html');
        $dom = pQuery::parseStr($html);

        $content_html = '';
        $ins = MethodFiled::where('trend', 'in')->where('method_id', $method['id'])->select();
        $in_arr = [];
        foreach ($ins as $in) {
            $real_config = self::getRealConfigData($in);
            $method_name = 'sp_' . $in['config']['type'];
            if ($method_name == 'sp_') {
                $method_name = 'sp_input';
            }
            $in['html'] = self::$method_name($real_config, false, true);
            $in_arr[] = $in;
        }


        $last_count = 0;
        $count = count($in_arr);
        foreach ($in_arr as $i => $in) {
            if ($i == 0) {
                $content_html .= ' <div class="layui-form-item" style="position: relative">' . $in['html'];
                if ($in['config']['is_inline']) {
                    $last_count++;
                }
            } else {
                if ($last_count == 3 || !$in['config']['is_inline']) {
                    $content_html .= '</div>';
                    $last_count = 0;
                }
                $content_html .= ' <div class="layui-form-item" style="position: relative">' . $in['html'];
                if ($in['config']['is_inline']) {
                    $last_count++;
                }
            }


            if ($i == $count - 1) {
                $content_html .= '</div>';
            }
        }

        $controller = Controller::find($method['controller_id']);
        $field_pre_fix = Str::snake($controller['name']) . '__';
        $content_html .= <<<EOF
<?php
\$pubid = make_pubid();
?>
<input type="hidden" value="{\$pubid }" name="{$field_pre_fix}pubid" />
<input type="hidden" value="{\$pubid }" name="pubid" />
EOF;


        $dom->query('#content-wrapper')->html($content_html);

        return self::purifier($dom->html());
    }


    /**
     * methodUpdateViewCode
     * @param $method
     * @return string
     * @throws \Gajus\Dindent\Exception\RuntimeException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function methodUpdateViewCode($method): string
    {
        $html = file_get_contents('../app/auto/template/update.html');
        $dom = pQuery::parseStr($html);

        $content_html = '';
        $ins = MethodFiled::where('trend', 'in')->where('method_id', $method['id'])->select();
        $in_arr = [];
        foreach ($ins as $in) {
            $real_config = self::getRealConfigData($in);
            $method_name = 'sp_' . $in['config']['type'];
            if ($method_name == 'sp_') {
                $method_name = 'sp_input';
            }
            $in['html'] = self::$method_name($real_config, true, true);
            $in_arr[] = $in;
        }


        $last_count = 0;
        $count = count($in_arr);
        foreach ($in_arr as $i => $in) {
            if ($i == 0) {
                $content_html .= ' <div class="layui-form-item" style="position: relative">' . $in['html'];
                if ($in['config']['is_inline']) {
                    $last_count++;
                }
            } else {
                if ($last_count == 3 || !$in['config']['is_inline']) {
                    $content_html .= '</div>';
                    $last_count = 0;
                }
                $content_html .= ' <div class="layui-form-item" style="position: relative">' . $in['html'];
                if ($in['config']['is_inline']) {
                    $last_count++;
                }
            }


            if ($i == $count - 1) {
                $content_html .= '</div>';
            }
        }

        $controller = Controller::find($method['controller_id']);
        $field_pre_fix = Str::snake($controller['name']) . '__';

        $content_html .= '<input type="hidden" value="{$r.pubid}" name="pubid" />';

        $content_html .= <<<EOF
<input type="hidden" value="{\$r.{$field_pre_fix}pubid}" name="{$field_pre_fix}pubid" />
<input type="hidden" value="{\$r.{$field_pre_fix}pubid}" name="pubid" />
<input type="hidden" name="{$field_pre_fix}id" value="{:input('{$field_pre_fix}id')}">
EOF;


        $dom->query('#content-wrapper')->html($content_html);

        return self::purifier($dom->html());
    }


    /**
     * 列表模版代码
     * getListViewCode
     * @param $method
     * @return string
     * @throws \Gajus\Dindent\Exception\RuntimeException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function methodListViewCode($method): string
    {
        $html = file_get_contents('../app/auto/template/index.html');
        $dom = pQuery::parseStr($html);

        $controller = \app\auto\model\Controller::find($method['controller_id']);
        $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);
        $self_table_id = Table::where('name', $self_table_name)->value('id');


        $table_header_html = "";
        $table_body_html = '{foreach $data as $v}';
        $table_body_html .= "<tr>";
        $outs = MethodFiled::where('trend', 'out')->where('method_id', $method['id'])->select();
        $out_arr = [];
        foreach ($outs as $out) {
            $out_field = \app\auto\model\Field::find($out['field_id']);
            $out_table = \app\auto\model\Table::find($out_field['table_id']);
            $out['table_name'] = $out_table['name'];
            $out['field_name'] = $out_field['name'];
            $out['fields'] = \app\auto\model\Field::where('table_id', $out_table['id'])->select();
            $out['alias'] = str_replace(env('DATABASE.PREFIX'), '', $out_table['name']) . '__' . $out_field['name'];
            $out_arr[] = $out;


            if ($out_field['name'] == 'id') {
                $table_header_html .= "<th style='width: 50px;'>{$out_field['comment']}</th>";
            } else {
                if ($self_table_id != $out_field['table_id']) {
                    $table_header_html .= "<th>{$out_field['config']['comment']}</th>";

                } else {
                    $table_header_html .= "<th>{$out_field['comment']}</th>";

                }
            }


            switch ($out_field['config']['type']) {
                case 'radio':
                case 'select':

                    $map_name = $out['alias'] . '_map';
                    $map = self::getDataSetOptions(self::getRealConfigData($out), true);
                    $str = (new ValueGenerator($map))->generate();
                    $table_body_html .= <<<EOF
<td>
<?php
\${$map_name} = {$str};
?>
    {if \$v.{$out['alias']}!==''}
    {\${$map_name}[\$v.{$out['alias']}]}
    {else/}
    -
    {/if}
</td>
EOF;
                    break;
                case 'image':
                    $table_body_html .= <<<EOF
<td>
    {if \$v.{$out['alias']}}
    <a class="fancybox"  href="{\$v.{$out['alias']}}">
    <img src="{\$v.{$out['alias']}}"  draggable="false" style="max-width: 100px; max-height: 50px;object-fit:cover;">
    </a>
    {else/}
    -
    {/if}
</td>
EOF;
                    break;

                case 'file':
                    $table_body_html .= <<<EOF
<td>
  {if \$v.{$out['alias']}}
  <span style="cursor: pointer" onclick="openFile(this)" data-filepath="{\$v.{$out['alias']}}"><img style="height: 30px" src="/static/admin/img/filetype/{:strtoupper(pathinfo(\$v.{$out['alias']},PATHINFO_EXTENSION))}.png" alt=""></span>
  <span style="cursor: pointer"  data-filepath="{\$v.{$out['alias']}}" onclick="downLoadFile(this)"><img style="height: 30px" src="/static/admin/img/download.png" alt=""></span>
  {else/}
  -
  {/if}
</td>
EOF;
                    break;

                case 'video':
                    $table_body_html .= <<<EOF
<td>
  {if \$v.{$out['alias']}}
  <span style="cursor: pointer" onclick="playVideoSrc('{\$v.{$out['alias']}}')" data-filepath="{\$v.{$out['alias']}}"><img style="height: 30px" src="/static/admin/img/filetype/{:strtoupper(pathinfo(\$v.{$out['alias']},PATHINFO_EXTENSION))}.png" alt=""></span>
  <span style="cursor: pointer"  data-filepath="{\$v.{$out['alias']}}" onclick="downLoadFile(this)"><img style="height: 30px" src="/static/admin/img/download.png" alt=""></span>
  {else/}
  -
  {/if}
</td>
EOF;

                    break;
                case 'morepic':
                    $table_body_html .= <<<EOF
<td style="overflow: scroll;text-overflow: clip;">
<?php
\$more_img_arr = explode( "\\r\\n", \$v['{$out['alias']}'] );
\$split_img_arr = [];
foreach (\$more_img_arr as \$img){
    if(\$img){
        \$split_img_arr[] =  explode('||', \$img);
    }
}
?>
    {foreach \$split_img_arr as \$img}
    <a class="fancybox"  href="{\$img[1]}">
    <img src="{\$img[0]}"  draggable="false" style="max-width: 100px; max-height: 50px;object-fit:cover;">
    </a>
    {/foreach}
</td>
EOF;
                    break;
                default:
                    $table_body_html .= "<td title='{\$v.{$out['alias']}}'>{\$v.{$out['alias']}}</td>";
                    break;
            }
        }
        $table_header_html .= '<th>操作</th>';
        $table_body_html .= self::getListMethodHtml($method);
        $table_body_html .= "</tr>";
        $table_body_html .= "{/foreach}";
        $dom->query('#table-header')->html($table_header_html);
        $dom->query('#table-body')->html($table_body_html);
        $right_search_html = self::getListMethodRightHeadHtml($method);
        $dom->query('#header-right')->html($right_search_html);

        $dom->query('#header-left')->html(static::getTopMethodHtml($method));

        return self::purifier($dom->html());
    }


    /**
     * getListMethodRightHeadHtml
     * @param $method
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getListMethodRightHeadHtml($method): string
    {
        $html = '';
        $ins = MethodFiled::where('trend', 'in')->where('method_id', $method['id'])->select();
        foreach ($ins as $in) {
            if ($in->ifield->name === 'id') {
                $html .= self::sc_relation_select(self::getRealConfigData($in));
            } else {
                if (in_array($in['config']['type'], ['radio', 'select'])) {
                    $html .= self::sc_select(self::getRealConfigData($in));
                } elseif (in_array($in['config']['type'], ['time'])) {
                    $html .= self::sc_time_range(self::getRealConfigData($in));
                } else {
                    $html .= self::sc_input(self::getRealConfigData($in));
                }
            }

        }
        if ($html) {
            $html .= <<<EOF
<div class="layui-inline">
    <button type="submit" class="layui-btn layuiadmin-btn-list" lay-submit lay-filter="LAY-app-contlist-search">
        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
    </button>
</div>
EOF;

        }
        return $html;
    }


    /**
     * 获取列表操作html
     * getListMethodHtml
     * @param $method
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getListMethodHtml($method): string
    {
        $html = '';
        foreach ($method['view_config']['list'] as $list_method_id) {
            $html .= static::getMethodBtnHtml($list_method_id) . "\n";
        }
        return '<td>' . "\n" . $html . '</td>';
    }


    /**
     * 获取顶部操作html
     * getTopMethodHtml
     * @param $method
     * @return string
     */
    public static function getTopMethodHtml($method): string
    {
        $html = '';
        foreach ($method['view_config']['top'] as $list_method_id) {
            $html .= static::getMethodBtnHtml($list_method_id, '');
        }
        return $html;
    }


    /**
     * 根据method_id获取方法按钮html
     * getMethodBtnHtml
     */
    public static function getMethodBtnHtml($method_id, $size_class = 'layui-btn-sm'): string
    {
        $method = Method::find($method_id);
        $controller = Controller::find($method['controller_id']);
        $pre_name = Str::snake($controller['name']);
        $table_name = env('DATABASE.PREFIX') . $pre_name;
        $table = Table::where('name', $table_name)->find();
        if ($method['is_iframe']) {
            $class = 'iframe';
        } else {
            $class = 'ajax_del';
        }
        $html = <<<EOF
<span class="layui-btn {$size_class} {$method['style']} {$class} " data-href="{:url('{$method['name']}',['{$pre_name}__id'=> \$v.{$pre_name}__id])}"  data-title="{$table['comment']}-{$method['title']}"  data-msg="{$method['msg']}"  data-height="{$method['height']}" data-width="{$method['width']}">{$method['title']}</span>
EOF;
        return $html;

    }


    /**
     * 美化html
     * purifier
     * @param $html
     * @return string
     * @throws \Gajus\Dindent\Exception\RuntimeException
     */
    public static function purifier($html): string
    {
        $indenter = new \Gajus\Dindent\Indenter();
        return $indenter->indent($html);
    }


    /**
     * getViewDir
     * @param $method
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getViewPath($method): string
    {
        $controller = Controller::find($method['controller_id']);
        $app = App::find($controller['app_id']);
        $app_path = "../app/{$app['name']}/";
        $view_path = $app_path . 'view/';
        $view_dir = $view_path . Str::snake($controller['name']);
        if (!is_dir($view_dir)) {
            mkdir($view_dir);
        }
        return $view_dir . '/' . Str::snake($method['name']) . '.html';
    }


}
